package com.njbw.design_pattern.created.factory.abstractFactory;

import com.njbw.design_pattern.created.factory.abstractFactory.product.IResource;
import com.njbw.design_pattern.created.factory.abstractFactory.resourceFactory.IResourceLoader;

import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

/**
 * @author 黄侯淳
 * @since JDK 1.8
 */
public class ResourceLoader {

    /**
     * 资源加载器
     * 版本一
     */
    // private IResourceLoader resourceLoader;

    /**
     * 资源加载器缓存
     * 版本二
     */
    private static final Map<String, IResourceLoader> RESOURCE_LOADER_CACHE = new HashMap<>(8);

    // 版本二
    /*static {
        RESOURCE_LOADER_CACHE.put("http", new HttpResourceLoader());
        RESOURCE_LOADER_CACHE.put("file", new FileResourceLoader());
        RESOURCE_LOADER_CACHE.put("classpath", new ClasspathResourceLoader());
        RESOURCE_LOADER_CACHE.put("ftp", new FtpResourceLoader());
        RESOURCE_LOADER_CACHE.put("default", new DefaultResourceLoader());
    }*/

    // 版本三：终极版本     加载配置文件到缓存
    // 1、完全满足开闭原则，当需要扩充需求时，只需要新增实现和修改配置文件，不需要修改一行代码
    // 2、资源可以缓存吗？假如每次获取的资源也是一样的，那缓存资源有必要吗？  资源不缓存，资源加载器缓存（为什么可以缓存工厂？因为工厂无状态，只负责创建，但是创建资源本身很复杂）
    // 3、产品不能缓存，因为每次获取的资源不一样，而且资源是有状态的
    static {
        InputStream is = Thread.currentThread().getContextClassLoader()
                .getResourceAsStream("resourceLoader3.properties");
        Properties properties = new Properties();
        try {
            properties.load(is);
            for (Map.Entry<Object, Object> entry : properties.entrySet()) {
                String key = entry.getKey().toString();
                Class<?> clazz = Class.forName(entry.getValue().toString());
                Object obj = clazz.getConstructor().newInstance();
                if (obj instanceof IResourceLoader) {
                    IResourceLoader loader = (IResourceLoader) obj;
                    RESOURCE_LOADER_CACHE.put(key, loader);
                }
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 加载资源
     * 核心业务逻辑部分不要耦合我们的创建逻辑
     * 创建逻辑交给工厂类去做
     *
     * @param url file:// http:// ftp:// classpath://
     * @return 资源类
     */
    public IResource loadPicture(String url) {
        // 1.根据 url 获取前缀
        String prefix = getPrefix(url);

        // 2.根据前缀选择不同的工厂，生产独自的产品
        // 隐藏各自创建逻辑
        /* 版本一
        if ("http".equals(prefix)) {
            resourceLoader = new HttpResourceLoader();
        } else if ("file".equals(prefix)) {
            resourceLoader = new FileResourceLoader();
        } else if ("classpath".equals(prefix)) {
            resourceLoader = new ClasspathResourceLoader();
        } else if ("ftp".equals(prefix)) {
            resourceLoader = new FtpResourceLoader();
        } else {
            resourceLoader = new DefaultResourceLoader();
        }
        return resourceLoader.load(url);*/
        // 版本二 和 三
        return RESOURCE_LOADER_CACHE.getOrDefault(prefix, RESOURCE_LOADER_CACHE.get("default")).loadPictureResource(url);
    }

    /**
     * 获取前缀
     *
     * @param url 资源路径
     * @return 前缀
     */
    private String getPrefix(String url) {
        if (null == url || !url.contains(":")) {
            throw new ResourceLoadException("传入的资源 url 不合法");
        }
        return url.split(":")[0];
    }
}
